package com.chaos.framework.web.interceptor.handler;

import com.chaos.framework.web.annotation.ManageLoginToken;
import com.chaos.framework.web.exception.AuthenticationException;
import com.chaos.framework.web.service.login.ILoginService;
import com.chaos.framework.model.constant.RoleConstant;
import com.chaos.framework.model.dto.login.manage.ManageLoginUser;
import com.chaos.framework.model.dto.result.ResultEnum;
import com.chaos.framework.web.dto.login.manage.JwtData;
import com.chaos.framework.web.service.JwtService;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class ManageLoginHandler {
    @Qualifier("mnLoginService")
    @Autowired(required = false)
    ILoginService mnLoginService;

    @Autowired
    private JwtService jwtService;

    public boolean handler(HttpServletRequest httpServletRequest, Method method) {
        ManageLoginToken manageLoginToken = method.getAnnotation(ManageLoginToken.class);
        if (manageLoginToken.required()) {
            if (mnLoginService == null) {
                return false;
            }
            String token = httpServletRequest.getHeader("token");
            ManageLoginUser loginUser = handleManageLogin(token, httpServletRequest);
            List<String> result = Arrays.asList(manageLoginToken.roles());
            ArrayList<String> roles = new ArrayList<>(result);
            if (!roles.contains(RoleConstant.GUEST)) {
                String role = loginUser.getRoleName();
                if (!roles.contains(role)) {
                    return false;
                }
            }
        }
        return true;
    }

    private ManageLoginUser handleManageLogin(String token, HttpServletRequest httpServletRequest) {
        if (StringUtils.isEmpty(token)) {
            throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "无效Token，请重新登录", httpServletRequest);
        }
        JwtData jwtData;
        try {
            jwtData = jwtService.getJwtData(token);
        } catch (ExpiredJwtException e) {
            String userMu = (String) e.getClaims().get("userMu");
            String refresh = mnLoginService.refreshToken(userMu);
            if (StringUtils.isEmpty(refresh)) {
                throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "Token续签失败，请重新登录", httpServletRequest);
            }
            throw new AuthenticationException(ResultEnum.REFRESH_TOKEN.getCode(), refresh, httpServletRequest);
        }
        if (jwtData.getUserMu() == null) {
            throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "Token信息错误，请重新登录", httpServletRequest);
        }
        ManageLoginUser loginUser;
        try {
            loginUser = (ManageLoginUser) mnLoginService.getLoginUser(jwtData.getUserMu());
        } catch (Exception e) {
            throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "无效token，请重新登录", httpServletRequest);
        }
        if (StringUtils.isEmpty(loginUser)) {
            throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "登录过期，请重新登录", httpServletRequest);
        }
        if (!token.equals(loginUser.getToken())) {
            throw new AuthenticationException(ResultEnum.LOGIN_AGAIN.getCode(), "Token更新，请重新登录", httpServletRequest);
        }
        return loginUser;
    }


}
